class String
  
  # <b>Selects the part based upon count. Giving you control over the syntax.</b>
  # 
  # The syntax:
  # * <tt>"{$N}".pluralize_for(int)</tt> 
  # * <tt>"{post|posts}".pluralize_for(int)</tt>
  # * <tt>"one post ~~ more posts".pluralize_for(int)</tt>
  # * <tt>"no posts ~~ one post ~~ more posts".pluralize_for(int)</tt> 
  # * <tt>"no posts ~~ one post ~~$N<6: more posts ~~else: large amount".pluralize_for(int) </tt>
  # * <tt>"click {1:here} for more info".pluralize_for(int) { |array| array[1] = link_to(array[i], url) if array[i] </tt>
  #
  # Tip: ~~$N>=3:-syntax is eval'ed, so check your source code! Also, if you decide to use it, it's better to specify it everywhere, not just the last parts.


  
  def pluralize_for(count)

    # get the value properly, so we can manipulate it
    str = self.to_s.clone

    # examine which part of it we need to fetch
    str = __get_partialized_string(str, count)

    # replace the count value, if any left
    str.gsub!("{$N}", count.to_s) if str.include?("{$N}")

    # replace {single|plural} with either single or plural
    if str =~ /\{([^|\{]*)\|([^\}]*)\}/
      single = $1.clone
      plural = $2.clone
      str.gsub!(/\{([^|\{]*)\|([^\}]*)\}/, (count == 1 ? single : plural))
    end

	
	# do some replacements with {1:foo}
    if block_given?
      
      # find the substitution parts
      matched = str.scan(/\{(\d+):([^\}]+)\}/)
      # do some reordering
      array = []
      matched.each do |x|
        array[x[0].to_i] = x[1].to_s
      end

      # let the others edit it if they like
      yield array

      # replace the block with the new values
      array.size.times do |x|
        str.gsub!(/\{#{x}:([^\}]+)\}/,array[x].to_s)
      end
    end
	
    str
  end


  private

  def __get_partialized_string(str, count)
    parts = str.split('~~')
    if parts.size > 1
      array = case parts.size
        when 2 then ['$N==1:', 'else:']
        when 3 then ['$N==0:', '$N==1:', 'else:']
        else
          ['$N==1:','$N!=1:']
        end
      parts.size.times do |i|
        parts[i] = array[i] + parts[i] unless parts[i] =~ /^\S*:/
        c = parts[i].split(/:\s*/,2)
        if c[0] == 'else'
          return c[1]
        else
          return c[1] if eval(c[0].gsub('$N',count.to_s))
        end
      end
    end
    return str
  end
end
